package com.xiaoju.manhattan.optimus.util;

import com.xiaoju.manhattan.optimus.external.huaxia.dto.HxCardBindingResponse;
import lombok.extern.log4j.Log4j2;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
import java.io.StringReader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * Created by lichengwen on 16/10/10.
 */
@Log4j2
public class XmlUtils
{
    private static final ConcurrentHashMap<Class<?>, Unmarshaller> CACHE = new ConcurrentHashMap<>();
    
    public static <T> T unmarshal(String xml, Class<T> type) {
        XMLInputFactory xif = XMLInputFactory.newFactory();
        StringReader strReader = new StringReader(xml);
        StreamSource ss = new StreamSource(strReader);
        XMLStreamReader xsr = null;
        try {
            try {
                xsr = xif.createXMLStreamReader(ss);
            } catch (XMLStreamException e) {
                throw new RuntimeException(e);
            }
            try {
                Unmarshaller unmarshaller = CACHE.get(type);
                if (unmarshaller == null) {
                    JAXBContext jc = JAXBContext.newInstance(type);
                    unmarshaller = jc.createUnmarshaller();
                    CACHE.putIfAbsent(type, unmarshaller);
                }
                JAXBElement<T> jb = unmarshaller.unmarshal(xsr, type);
                return jb.getValue();
            } catch (JAXBException e) {
                throw new RuntimeException(e);
            }
        } finally {
            if (xsr != null) {
                try {
                    xsr.close();
                } catch (XMLStreamException e) {
                    log.error("an error occurred when closing XMLStreamReader");
                }
            }
        }
    }
    
    public static void main(String[] args)
    {
        String xml = "<Message>\n" +
                     "    <applicationNo>";
        String s = "asdf</applicationNo>\n" +
                     "    <status>ssss</status>\n" +
                     "    <contractNo>ccccccc</contractNo>\n" +
                     "    <sign>eoirhgaf</sign>\n" +
                     "    <currentAccountAgreementNo>4htwert6hwrtg</currentAccountAgreementNo>\n" +
                     "</Message>";
        for (int i = 0; i < 20; i++) {
            final String str = xml + i + s;
            new Thread() {
                public void run() {
                    HxCardBindingResponse obj = XmlUtils.unmarshal(str, HxCardBindingResponse.class);
                    System.out.println(obj);
                }
            }.start();
        }
    
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
}
